#include "gd32h7xx.h"
#include <stdio.h>
#include <stdbool.h>
#include "gd32h759i_eval.h"
#include "systick.h"
#include "string.h"

/* RS485配置参数 */
#define RS485_USART         USART2
#define RS485_BAUDRATE      115200      // 波特率
#define MAX_RX_BUFFER_SIZE  256         // 最大接收缓冲区大小
#define TEST_TIMEOUT_MS     3000        // 无数据超时时间
#define MAX_FRAME_SAMPLES   100         // 最大帧采样数

/* 全局变量 */
uint8_t rx_buffer[MAX_RX_BUFFER_SIZE];  // 接收缓冲区
volatile uint8_t rx_len = 0;            // 接收数据长度
volatile FlagStatus rx_complete = RESET;// 接收完成标志
volatile FlagStatus tx_complete = SET;  // 发送完成标志

/* 测试统计变量 */
// 接收统计
volatile uint32_t rx_total_bytes = 0;   // 总接收字节数
volatile uint32_t rx_frame_count = 0;   // 接收帧总数
volatile uint32_t rx_frame_intervals[MAX_FRAME_SAMPLES]; // 接收帧间隔
volatile uint8_t rx_interval_idx = 0;   // 接收间隔索引

// 发送统计（仅保留必要信息）
volatile uint32_t tx_total_bytes = 0;   // 总发送字节数
volatile uint32_t tx_frame_count = 0;   // 发送帧总数

// 时间戳
volatile uint32_t test_start_time = 0;  // 测试开始时间
volatile uint32_t last_rx_time = 0;     // 最后接收时间
volatile uint32_t last_tx_time = 0;     // 最后发送时间
volatile bool test_in_progress = false; // 测试状态

/* 函数声明 */
void rs485_gpio_config(void);
void rs485_usart_config(void);
void send_response(void);               // 发送响应数据
void cache_enable(void);
uint32_t get_tick_count(void);
void print_test_results(void);

/* 使能Cache */
void cache_enable(void) {
    SCB_EnableICache();
    SCB_EnableDCache();
}

/* 配置RS485 GPIO引脚 */
void rs485_gpio_config(void) {
    rcu_periph_clock_enable(RCU_GPIOD);
    rcu_periph_clock_enable(RCU_USART2);
    
    /* PD8 (TX) 配置为复用功能 */
    gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
    gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_8);
    gpio_af_set(GPIOD, GPIO_AF_7, GPIO_PIN_8);
    
    /* PD9 (RX) 配置为复用功能 */
    gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
    gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_9);
    gpio_af_set(GPIOD, GPIO_AF_7, GPIO_PIN_9);
}

/* 配置USART2 */
void rs485_usart_config(void) {
    usart_deinit(USART2);
    
    /* 基本参数配置 */
    usart_baudrate_set(USART2, RS485_BAUDRATE);
    usart_word_length_set(USART2, USART_WL_8BIT);
    usart_stop_bit_set(USART2, USART_STB_1BIT);
    usart_parity_config(USART2, USART_PM_NONE);
    
    /* 禁用硬件流控 */
    usart_hardware_flow_cts_config(USART2, USART_CTS_DISABLE);
    usart_hardware_flow_rts_config(USART2, USART_RTS_DISABLE);
    
    /* 使能收发 */
    usart_receive_config(USART2, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART2, USART_TRANSMIT_ENABLE);
    
    /* 使能接收中断和IDLE中断 */
    usart_interrupt_enable(USART2, USART_INT_RBNE);
    usart_interrupt_enable(USART2, USART_INT_IDLE);
    nvic_irq_enable(USART2_IRQn, 1U, 0U);
    
    usart_enable(USART2);
}

/* 发送响应数据 */
void send_response(void) {
    if (rx_len == 0) return;
    
    tx_complete = RESET;
    uint32_t current_time = get_tick_count();
    
    // 通过USART2发送数据
    for (uint8_t i = 0; i < rx_len; i++) {
        usart_data_transmit(RS485_USART, rx_buffer[i]);
        while (usart_flag_get(RS485_USART, USART_FLAG_TBE) == RESET);
    }
    while (usart_flag_get(RS485_USART, USART_FLAG_TC) == RESET);
    
    // 更新发送统计
    tx_frame_count++;
    tx_total_bytes += rx_len;
    last_tx_time = current_time;
    tx_complete = SET;
}

/* USART2接收中断 */
void USART2_IRQHandler(void) {
    static uint32_t last_idle_time = 0;
    uint32_t current_time = get_tick_count();
    
    if (usart_interrupt_flag_get(USART2, USART_INT_FLAG_RBNE) == SET) {
        // 接收数据字节
        uint8_t data = usart_data_receive(USART2);
        
        // 长度校验：固定8字节，超过则丢弃
        if (rx_len < 8) {
            rx_buffer[rx_len++] = data;
            
            // 当收到第8个字节时，立即标记接收完成
            if (rx_len == 8) {
                // 记录接收帧间隔（当前时间 - 上一次接收时间）
                if (rx_frame_count > 0 && rx_interval_idx < MAX_FRAME_SAMPLES) {
                    rx_frame_intervals[rx_interval_idx++] = current_time - last_idle_time;
                }
                
                if (!test_in_progress) {
                    // 开始新测试
                    test_in_progress = true;
                    test_start_time = current_time;
                    last_rx_time = current_time;
                    last_tx_time = current_time;
                    rx_frame_count = 1;
                    rx_total_bytes = rx_len;
                } else {
                    rx_frame_count++;
                    rx_total_bytes += rx_len;
                }
                
                last_idle_time = current_time;
                last_rx_time = current_time;
                rx_complete = SET;
            }
        }
        usart_interrupt_flag_clear(USART2, USART_INT_FLAG_RBNE);
    } 
    else if (usart_interrupt_flag_get(USART2, USART_INT_FLAG_IDLE) == SET) {
        // IDLE中断：处理异常情况
        usart_interrupt_flag_clear(USART2, USART_INT_FLAG_IDLE);
        uint8_t temp = usart_data_receive(USART2);
        
        // 仅当数据长度为8时认为有效
        if (rx_len == 8) {
            // 记录接收帧间隔
            if (rx_frame_count > 0 && rx_interval_idx < MAX_FRAME_SAMPLES) {
                rx_frame_intervals[rx_interval_idx++] = current_time - last_idle_time;
            }
            
            if (!test_in_progress) {
                test_in_progress = true;
                test_start_time = current_time;
                last_rx_time = current_time;
                last_tx_time = current_time;
                rx_frame_count = 1;
                rx_total_bytes = rx_len;
            } else {
                rx_frame_count++;
                rx_total_bytes += rx_len;
            }
            
            last_idle_time = current_time;
            last_rx_time = current_time;
            rx_complete = SET;
        } else {
            // 丢弃不完整帧
            printf("警告: 收到不完整帧，长度=%d (期望8字节)\n", rx_len);
            rx_len = 0;
        }
    }
}

/* 打印测试结果（统计最大接收速率） */
void print_test_results(void) {
    uint32_t total_time_ms = last_rx_time - test_start_time;
    if (total_time_ms == 0) total_time_ms = 1; // 避免除零
    
    float total_time_sec = total_time_ms / 1000.0f;
    
    // 计算最大接收速率（基于最小帧间隔）
    float rx_max_rate = 0.0f;
    for (uint8_t i = 0; i < rx_interval_idx; i++) {
        if (rx_frame_intervals[i] > 0) {
            float rate = (float)8 * 1000.0f / rx_frame_intervals[i]; // 8字节/帧
            if (rate > rx_max_rate) rx_max_rate = rate;
        }
    }
    
    // 计算平均接收速率
    float rx_avg_rate = rx_total_bytes / total_time_sec;
    
    // 输出接收统计结果
    printf("\n[测试结束] 接收统计结果：\n");
    printf("  - 总测试时间：%.2f 秒\n", total_time_sec);
    printf("  - 总接收帧数：%lu\n", rx_frame_count);
    printf("  - 总接收字节数：%lu\n", rx_total_bytes);
    printf("  - 平均接收速率：%.2f 字节/秒\n", rx_avg_rate);
    printf("  - 最大接收速率：%.2f 字节/秒\n", rx_max_rate);
    printf("  - 测试波特率：%d\n", RS485_BAUDRATE);
    printf("----------------------------------------\n");
    printf("等待下一次测试...\n\n");
}

int main(void) {
    /* 系统初始化 */
    cache_enable();
    systick_config();
    gd_eval_com_init(EVAL_COM);  // 调试串口
    
    /* 初始化RS485 */
    rs485_gpio_config();
    rs485_usart_config();
    printf("===== RS485接收速率测试初始化完成 =====\n");
    printf("请通过串口发送8字节数据，设备将回传并统计接收性能\n\n");
    
    /* 主循环 */
    while (1) {
        // 接收完成后立即发送响应
        if (rx_complete) {
            // 打印接收到的8字节数据
            printf("收到有效帧: ");
            for (int i = 0; i < rx_len; i++) {
                printf("%02X ", rx_buffer[i]);
            }
            printf("\n");
            
            send_response();  // 回传数据
            rx_complete = RESET;
            rx_len = 0;       // 清空接收缓冲区
        }
        
        // 超时判断
        if (test_in_progress && (get_tick_count() - last_rx_time > TEST_TIMEOUT_MS)) {
            print_test_results();
            
            // 重置测试参数
            test_in_progress = false;
            rx_total_bytes = 0;
            rx_frame_count = 0;
            rx_interval_idx = 0;
            memset((void*)rx_frame_intervals, 0, sizeof(rx_frame_intervals));
            tx_total_bytes = 0;
            tx_frame_count = 0;
        }
        
        delay_1ms(10);
    }
}

/* 获取系统滴答时间 */
uint32_t get_tick_count(void) {
    static uint32_t tick_count = 0;
    tick_count++;
    return tick_count;
}

/* 重定向printf到调试串口 */
int fputc(int ch, FILE *f) {
    usart_data_transmit(EVAL_COM, (uint8_t)ch);
    while (usart_flag_get(EVAL_COM, USART_FLAG_TBE) == RESET);
    return ch;
}